<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>生成曲线</title>
</head>

<body>
    <script>
        var designW = 1280
        var designH = 720
    </script>
    <canvas id="canvas" width="1280" height="720"></canvas>
    <p>---------------------------------------------------------------------------------------------------------------------------------
    </p>
    <input id="inputCurveStr" type="text"></input>
    <button onclick="createCurve()">生成曲线</button>
    <input id="inputCoorScale" type="text">缩放倍率</input>
    <p>样例曲线</p>
    <select id="curveTemplete">

    </select>

    <script>
        let defaultCoorScale = 1
        let inputCurveStr = document.getElementById('inputCurveStr')
        let canvas = document.getElementById('canvas')
        canvas.style.width = designW
        canvas.style.height = designH
        let inputCoorScale = document.getElementById('inputCoorScale')
        let curveTemplete = document.getElementById('curveTemplete')
        curveTemplete.onchange = onCurveTempleteChange

        let context = canvas.getContext("2d");

        let scaleRatio = 1
        inputCoorScale.value = defaultCoorScale

        let curveTempeleteData = []
        curveTempeleteData.push({ curveStr: "x", coorScale: 100 })
        curveTempeleteData.push({ curveStr: "x*x", coorScale: 150 })
        curveTempeleteData.push({ curveStr: "x*x*x", coorScale: 200 })
        curveTempeleteData.push({ curveStr: "x*x*(3-2*x)", coorScale: 100 })
        curveTempeleteData.push({ curveStr: "Math.sin(x)", coorScale: 100 })
        curveTempeleteData.push({ curveStr: "Math.cos(x)", coorScale: 100 })
        curveTempeleteData.push({ curveStr: "1/x", coorScale: 100 })
        curveTempeleteData.push({ curveStr: "Math.log10(x)", coorScale: 100 })
        curveTempeleteData.push({ curveStr: "Math.pow(Math.E,x)", coorScale: 100 })
        curveTempeleteData.push({ curveStr: "(1-1*x)*(1-1*x)*(-3)+2*x*(1-1*x)*2+x*x*5", coorScale: 30 })




        adpteView();
        createCurveTempletes();

        function onCurveTempleteChange() {
            updateCurCurveTemplete()
        }

        function createCurveTempletes() {
            for (let i = 0; i < curveTempeleteData.length; i++) {
                let oneData = curveTempeleteData[i];
                let option = document.createElement("option");
                option.value = i
                option.selected = i == 0
                option.text = oneData.curveStr
                curveTemplete.add(option)
            }
            onCurveTempleteChange()
        }

        function updateCurCurveTemplete() {
            let selectedOption = curveTemplete.options[curveTemplete.selectedIndex]
            let data = curveTempeleteData[selectedOption.value];
            inputCoorScale.value = data.coorScale
            inputCurveStr.value = data.curveStr
            createCurve();
        }

        function drawAxies() {
            // 
            // let startY = -designH / 2
            // let endY = designH / 2

            context.beginPath();
            context.moveTo(0, designH / 2);
            context.lineTo(designW, designH / 2);
            context.stroke();

            context.beginPath();
            context.moveTo(designW / 2, 0);
            context.lineTo(designW / 2, designH);
            context.stroke();

            let coordinateScale = Number(inputCoorScale.value) || 1
            let leftX = -designW / 2
            let rightX = designW / 2
            let rightIndex = Math.floor(rightX / coordinateScale)
            let leftIndex = -Math.floor(-leftX / coordinateScale)

            let fontSize = 20;//对应coordinateScale为100时的字体大小
            fontSize = 20 / 150 * coordinateScale
            fontSize = Math.max(15, fontSize)
            context.font = fontSize + "px Georgia";

            let xAix = []
            let yAix = []

            for (let i = leftIndex; i <= rightIndex; i++) {
                let y = designH / 2 - 2;
                let x = i * coordinateScale + designW / 2;
                context.strokeText(i + "", x, y);
                xAix.push(x)
            }

            let topY = designH / 2
            let bottomY = -designH / 2
            let topIndex = Math.floor(topY / coordinateScale)
            let bottomIndex = -Math.floor(-bottomY / coordinateScale)


            for (let i = bottomIndex; i <= topIndex; i++) {
                if (i == 0) {
                    continue
                }
                let x = designW / 2 + 5;
                let y = -i * coordinateScale + designH / 2;
                context.strokeText(i + "", x, y);
                yAix.push(y)
            }

            context.strokeStyle = "#ffffff";
            context.beginPath()
            context.lineWidth = 0.4
            for (let i = 0; i < xAix.length; i++) {
                if (xAix[i] == designW / 2) {
                    continue
                }
                drawDotLine(xAix[i], 0, xAix[i], designH)
            }
            for (let i = 0; i < yAix.length; i++) {
                if (yAix[i] == designH / 2) {
                    continue
                }
                drawDotLine(0, yAix[i], designW, yAix[i])
            }
            context.stroke()
        }

        function drawDotLine(startX, startY, endX, endY) {
            // context.beginPath()
            let xArr = [startX]
            let yArr = [startY]
            let space = 20
            let isX = startX != endX
            let start = isX ? startX : startY
            let end = isX ? endX : endY
            let curStart = start
            while (curStart < end) {
                curStart += space
                let persent = (curStart - start) / (end - start)
                if(isX){
                    xArr.push(curStart)
                    yArr.push(startY + (endY - startY) * persent)
                }else{
                    yArr.push(curStart)
                    xArr.push(startX + (endX - startX) * persent)
                }
            }

            for (let i = 0; i < xArr.length; i++) {
                if (i % 2 == 0 && i + 1 < xArr.length) {
                    context.moveTo(xArr[i], yArr[i])
                    context.lineTo(xArr[i + 1], yArr[i + 1])
                }
            }
        }

        function adpteView() {
            let stageWidth = document.documentElement.clientWidth;
            let stageHeight = document.documentElement.clientHeight;
            let ratioW = stageWidth / designW
            let ratioH = stageHeight / designH
            scaleRatio = Math.min(ratioW, ratioH);
            context.scale(scaleRatio, scaleRatio);

            drawBg();
        }

        function clearView() {
            canvas.height = canvas.height
            adpteView()
        }

        function drawBg() {
            context.fillStyle = 'rgba(0,125,0,1)';
            context.fillRect(0, 0, canvas.width, canvas.height);
        }

        function meval(str, x) {
            str = str.replace(/x/g, x);
            return eval(str)
        }

        function createCurve() {
            clearView();
            setTimeout(() => {
                drawAxies();
                let coordinateScale = Number(inputCoorScale.value) || 1
                context.lineWidth = 2;
                context.strokeStyle = "#000000";

                let inputStr = inputCurveStr.value
                let startX = -designW / 2

                let endX = designW / 2
                context.beginPath();
                let index = 0
                for (let x = startX; x <= endX; x++) {
                    let posY = -meval(inputStr, x / coordinateScale) * coordinateScale + designH / 2
                    let posX = x + designW / 2
                    if (index == 0) {
                        context.moveTo(posX, posY);
                    } else {
                        context.lineTo(posX, posY);
                        context.moveTo(posX, posY);
                    }
                    index++
                }
                context.stroke();
            }, 0)
        }



    </script>



</body>

</html>